package com.ops.uitl.tapestry;

import org.apache.tapestry.IActionListener;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.RedirectException;
import org.apache.tapestry.event.PageEvent;
import org.apache.tapestry.event.PageRenderListener;

public abstract class AppPage extends ProtectPage implements PageRenderListener {

	public static final int MESSAGE_CONFIRM = 1;
	public static final int MESSAGE_WARNING = 2;
	public static final int MESSAGE_ERROR = 3;

	private String hintInfo;
	private String alertInfo;
	private String errorInfo;
	private long useTime;
	private boolean legalAccess;

	public String getAlertInfo() {
		return alertInfo;
	}
	public void setAlertInfo(String alertInfo) {
		this.alertInfo = alertInfo;
	}

	public String getErrorInfo() {
		return errorInfo;
	}
	public void setErrorInfo(String errorInfo) {
		this.errorInfo = errorInfo;
	}

	public String getHintInfo() {
		return hintInfo;
	}
	public void setHintInfo(String hintInfo) {
		this.hintInfo = hintInfo;
	}

	public boolean isLegalAccess() {
		return legalAccess;
	}
	public void setLegalAccess(boolean legalAccess) {
		this.legalAccess = legalAccess;
	}

	public long getUseTime() {
		return useTime;
	}
	public void setUseTime(long useTime) {
		this.useTime = useTime;
	}

	/**
	 * exist page data
	 *
	 * @return boolean
	 */
	public boolean existPageData() {
		return pd != null;
	}

	/**
	 * get page data
	 *
	 * @return PageData
	 * @throws Exception
	 */
	public PageData getPageData() throws Exception {
		if (!existPageData()) {
			pd = new PageData(getRequestCycle());
			AppContext ctx = (AppContext) getVisit();
			pd.setRouteEparchy(ctx.getLoginEpachyId());
			pd.setContext(ctx);
		}
		return (PageData) pd;
	}


	/**
	 *
	 * @param pd
	 * @param name
	 * @param defval
	 * @return
	 * @throws Exception
	 */
	private String getLoginParameter(PageData pd, String name, String defval) throws Exception {
		String[] names = pd.getParameters(name);
		if (names == null || names.length < 1) return defval;
		if ("null".equals(names[0])) return defval;
		return names[0];
	}

	/**
	 * page validate
	 *
	 * @param event
	 */
	public void pageValidate(PageEvent event) {
		if (log.isDebugEnabled()) log.debug(getPageName() + " validate...");
		setUseTime(System.currentTimeMillis());
		AppContext ctx = (AppContext) getVisit();

		String loginType = null, productMode = null, referer = null;
		boolean hasPriv = true;
		PageData pd = null;
		String refercheck = "true";
		String execmessage = "自动登陆失败";

		try {
			pd = getPageData();

			referer = pd.getRequest().getHeader("referer");
			productMode = common.getProperty("project/productmode");
			if ("true".equals(productMode) && !isLegalAccess()) {
				if (referer == null) {
					hasPriv = false;
					throw new RedirectException("component/Support.html");
				}
			}

			String randomCode = getLoginParameter(pd, "LOGIN_LOG_ID", "");
			ctx.setAttribute("LOGIN_LOG_ID", randomCode);

			if (!ctx.isValidate()) {
				log.error("登录已超时");
			}

		} catch (RedirectException e) {
			loginRedirectError(hasPriv, referer, refercheck, loginType);
		} catch (Exception e) {
			log.error(execmessage, e);
		} finally {
			try {
				pd.cleanupConnections();
			} catch (Exception e) {
				log.error(e);
			}
		}
	}




	/**
	 * login redirect error
	 * @param hasPriv
	 * @param referer
	 * @param refercheck
	 * @param loginType
	 * @throws RedirectException
	 */
	private void loginRedirectError(boolean hasPriv, String referer, String refercheck, String loginType) throws RedirectException {
		if (hasPriv) {
			if ("BOSS_GUI".equals(loginType)) {
				throw new RedirectException("GuiLogin.html");
			} else {
				throw new RedirectException("component/Timeout.html");
			}
		} else {
			if ("true".equals(refercheck)) {
				log.error(pd.getRequest().getRemoteAddr() + " illegal access " + referer);
			}
			throw new RedirectException("component/Support.html");
		}
	}

	/**
	 * page begin render
	 *
	 * @param event
	 */
	public void pageBeginRender(PageEvent event) {
		if (!getRequestCycle().isRewinding()) {
			String listener = getRequestCycle().getRequestContext().getParameter("listener");
			if (log.isDebugEnabled()) log.debug(getPageName() + " render..." + (listener == null ? "" : listener));

			try {
				if (listener != null && !"".equals(listener)) {
					redirectTo(listener);
				}
			} catch (Exception e) {
				log.error(e);
			}
		}
	}

	/**
	 * page detached
	 *
	 * @param event
	 */
	public void pageDetached(PageEvent event) {
		if (!getRequestCycle().isRewinding()) {
			if (log.isDebugEnabled()) log.debug(getPageName() + " detach...");

			if (existPageData()) {
				try {
					pd.cleanupConnections();
				} catch (Exception e) {
					log.error(e);
				}
			}

			AppContext ctx = (AppContext) getVisit();
			setUseTime(System.currentTimeMillis() - getUseTime());
			if (log.isDebugEnabled())
				if (log.isDebugEnabled()) log.debug(getPageName() + " load finish, " + ctx.getStaffId()
						+ " use time: " + ((double) getUseTime() / (double) 1000) + "s"
						+ " use memory: " + (Runtime.getRuntime().freeMemory() / (float) 1000000) + "/" + (Runtime.getRuntime().totalMemory() / (float)1000000) + "M");

			pd = null;
			setAlertInfo(null);
			setHintInfo(null);
			setErrorInfo(null);
		}
	}


	/**
	 * logout
	 * @param cycle
	 * @throws Exception
	 */
	public void logout(IRequestCycle cycle) throws Exception {
		PageData pd = getPageData();
		AppContext visit = (AppContext) pd.getContext();
		String login_type = visit.getLoginType();

		if (log.isDebugEnabled()) log.debug(getPageName() + " logout..." + visit.getSubSysCode() + "," + visit.getStaffId());

		pd.getSession().invalidate();

		pd.setContext(new AppContext());
	}

	/**
	 * redirect to
	 *
	 * @param event_name
	 * @return Exception
	 */
	public void redirectTo(String event_name) throws Exception {
		IActionListener listener = (IActionListener) getListeners()
				.getListener(event_name);
		listener.actionTriggered(this, getRequestCycle());
	}

	/**
	 * redirect to
	 *
	 * @param page_name
	 * @param event_name
	 * @return Exception
	 */
	public void redirectTo(String page_name, String event_name) throws Exception {
		IRequestCycle cycle = getRequestCycle();

		AppPage page = (AppPage) cycle.getPage(page_name);
		if (pd != null) {
			page.getPageData().getDBConns().putAll(pd.getDBConns());
		}
		cycle.activate(page);

		if (event_name != null && !"".equals(event_name)) {
			IActionListener listener = (IActionListener) page.getListeners()
					.getListener(event_name);
			listener.actionTriggered(page, page.getRequestCycle());
		}
	}

	/**
	 * redirect to message
	 *
	 * @param messageType
	 * @param message
	 * @param pageName
	 * @return Exception
	 */
	public void redirectToMsg(String message) throws Exception {
		redirectToMsg(MESSAGE_CONFIRM, message, null);
	}

	/**
	 * redirect to message
	 *
	 * @param message
	 * @param pageName
	 * @return Exception
	 */
	public void redirectToMsg(String message, String pageName) throws Exception {
		redirectToMsg(MESSAGE_CONFIRM, message, pageName, null);
	}

	/**
	 * redirect to message
	 *
	 * @param messageType
	 * @param message
	 * @param pageName
	 * @return Exception
	 */
	public void redirectToMsg(int messageType, String message) throws Exception {
		redirectToMsg(messageType, message, null);
	}

	/**
	 * redirect to message
	 *
	 * @param messageType
	 * @param message
	 * @param pageName
	 * @return Exception
	 */
	public void redirectToMsg(int messageType, String message, String pageName) throws Exception {
		redirectToMsg(messageType, message, pageName, null);
	}

	/**
	 * redirect to message
	 *
	 * @param message
	 * @param pageName
	 * @param listener
	 * @return Exception
	 */
	public void redirectToMsg(String message, String pageName, String listener) throws Exception {
		redirectToMsg(MESSAGE_CONFIRM, message, pageName, listener, null);
	}

	/**
	 * redirect to message
	 *
	 * @param messageType
	 * @param message
	 * @param pageName
	 * @param listener
	 * @return Exception
	 */
	public void redirectToMsg(int messageType, String message, String pageName, String listener) throws Exception {
		redirectToMsg(messageType, message, pageName, listener, null);
	}

	/**
	 * redirect to message
	 *
	 * @param message
	 * @param pageName
	 * @param listener
	 * @param target
	 * @return Exception
	 */
	public void redirectToMsg(String message, String pageName, String listener, String target) throws Exception {
		redirectToMsg(MESSAGE_CONFIRM, message, pageName, listener, target);
	}

	/**
	 * redirect to message
	 *
	 * @param messageType
	 * @param message
	 * @param pageName
	 * @param listener
	 * @param target
	 * @return Exception
	 */
	public void redirectToMsg(int messageType, String message, String pageName, String listener, String target) throws Exception {
		redirectToMsg(messageType, message, new String[] { pageName }, new String[] { listener }, null, new String[] { target });
	}

	/**
	 * redirect to message
	 *
	 * @param message
	 * @param pageNames
	 * @param listeners
	 * @return Exception
	 */
	public void redirectToMsg(String message, String[] pageNames, String[] listeners) throws Exception {
		redirectToMsg(MESSAGE_CONFIRM, message, pageNames, listeners, null, null);
	}

	/**
	 * redirect to message
	 *
	 * @param message
	 * @param pageNames
	 * @param listeners
	 * @param buttons
	 * @return Exception
	 */
	public void redirectToMsg(String message, String[] pageNames, String[] listeners, String[] buttons) throws Exception {
		redirectToMsg(MESSAGE_CONFIRM, message, pageNames, listeners, buttons, null);
	}

	/**
	 * redirect to message
	 *
	 * @param message
	 * @param pageNames
	 * @param listeners
	 * @param buttons
	 * @param targets
	 * @return Exception
	 */
	public void redirectToMsg(String message, String[] pageNames, String[] listeners, String[] buttons, String[] targets) throws Exception {
		redirectToMsg(MESSAGE_CONFIRM, message, pageNames, listeners, buttons, targets);
	}

	/**
	 * redirect to message
	 *
	 * @param messageType
	 * @param message
	 * @param pageNames
	 * @param listeners
	 * @return Exception
	 */
	public void redirectToMsg(int messageType, String message, String[] pageNames, String[] listeners) throws Exception {
		redirectToMsg(messageType, message, pageNames, listeners, null, null);
	}

	/**
	 * redirect to message
	 *
	 * @param messageType
	 * @param message
	 * @param pageNames
	 * @param listeners
	 * @param buttons
	 * @return Exception
	 */
	public void redirectToMsg(int messageType, String message, String[] pageNames, String[] listeners, String[] buttons) throws Exception {
		redirectToMsg(messageType, message, pageNames, listeners, buttons, null);
	}

	/**
	 * redirect to message
	 *
	 * @param messageType
	 * @param message
	 * @param pageNames
	 * @param listeners
	 * @param buttons
	 * @param targets
	 * @return Exception
	 */
	public void redirectToMsg(int messageType, String message, String[] pageNames, String[] listeners, String[] buttons, String[] targets) throws Exception {
		PageData pd = getPageData();
		for(int i=0;i<listeners.length;i++){
			if(listeners[i]==null || listeners[i]==""){listeners[i]="wade-nullListener";}
		}
		pd.setTransfer("$msg$message", message);
		pd.setTransfer("$msg$messageType", String.valueOf(messageType));
		pd.setTransfers("$msg$path", pageNames);
		pd.setTransfers("$msg$event", listeners);
		pd.setTransfers("$msg$button", buttons);
		pd.setTransfers("$msg$target", targets);
		redirectTo("component.Message", "setHintMessage");
	}

	/**
	 * redirect to message by popup
	 *
	 * @param message
	 * @return Exception
	 */
	public void redirectToMsgByPopup(String message) throws Exception {
		redirectToMsgByPopup(MESSAGE_CONFIRM, message);
	}

	/**
	 * redirect to message by popup
	 *
	 * @param message
	 * @param pageName
	 * @return Exception
	 */
	public void redirectToMsgByPopup(String message, String pageName) throws Exception {
		redirectToMsgByPopup(MESSAGE_CONFIRM, message, pageName);
	}

	/**
	 * redirect to message by popup
	 *
	 * @param message
	 * @param pageName
	 * @parmm listener
	 * @return Exception
	 */
	public void redirectToMsgByPopup(String message, String pageName, String listener) throws Exception {
		redirectToMsgByPopup(MESSAGE_CONFIRM, message, pageName, listener, "currentframe");
	}

	/**
	 * redirect to message by popup
	 *
	 * @param message
	 * @param pageName
	 * @parmm listener
	 * @param target
	 * @return Exception
	 */
	public void redirectToMsgByPopup(String message, String pageName, String listener, String target) throws Exception {
		redirectToMsgByPopup(MESSAGE_CONFIRM, message, pageName, listener, target);
	}

	/**
	 * redirect to message by popup
	 *
	 * @param messageType
	 * @param message
	 * @param func
	 * @return Exception
	 */
	public void redirectToMsgByPopup(int messageType, String message) throws Exception {
		redirectToMsgByScript(messageType, message, null, null);
	}

	/**
	 * redirect to message by popup
	 *
	 * @param messageType
	 * @param message
	 * @param pageName
	 * @return Exception
	 */
	public void redirectToMsgByPopup(int messageType, String message, String pageName) throws Exception {
		redirectToMsgByPopup(messageType, message, pageName, null);
	}

	/**
	 * redirect to message by popup
	 *
	 * @param messageType
	 * @param message
	 * @param pageName
	 * @param listener
	 * @return Exception
	 */
	public void redirectToMsgByPopup(int messageType, String message, String pageName, String listener) throws Exception {
		redirectToMsgByPopup(messageType, message, pageName, listener, null);
	}

	/**
	 * redirect to message by popup
	 *
	 * @param messageType
	 * @param message
	 * @param pageName
	 * @param listener
	 * @param target
	 * @return Exception
	 */
	public void redirectToMsgByPopup(int messageType, String message, String pageName, String listener, String target) throws Exception {
		redirectToMsgByScript(messageType, message, new String[] { "关闭" }, new String[] { "Wade.message.setReturnFunc('" + pageName + "', " + (listener == null ? "null" : "'" + listener + "'") + ", parameters, " + (target == null ? "null" : "'" + target + "'") + ")" });
	}

	/**
	 * redirect to message by script
	 *
	 * @param messageType
	 * @param message
	 * @param func
	 * @return Exception
	 */
	public void redirectToMsgByScript(String message, String func) throws Exception {
		redirectToMsgByScript(MESSAGE_CONFIRM, message, func);
	}

	/**
	 * redirect to message by script
	 *
	 * @param message
	 * @param buttons
	 * @param funcs
	 * @return Exception
	 */
	public void redirectToMsgByScript(String message, String[] buttons, String[] funcs) throws Exception {
		redirectToMsgByScript(MESSAGE_CONFIRM, message, buttons, funcs);
	}

	/**
	 * redirect to message by script
	 *
	 * @param messageType
	 * @param message
	 * @param func
	 * @return Exception
	 */
	public void redirectToMsgByScript(int messageType, String message, String func) throws Exception {
		redirectToMsgByScript(messageType, message, null, new String[] { func });
	}

	/**
	 * redirect to message by script
	 *
	 * @param messageType
	 * @param message
	 * @param buttons
	 * @param funcs
	 * @return Exception
	 */
	public void redirectToMsgByScript(int messageType, String message, String[] buttons, String[] funcs) throws Exception {
		PageData pd = getPageData();

		pd.setTransfer("$msg$message", message);
		pd.setTransfer("$msg$messageType", String.valueOf(messageType));
		pd.setTransfers("$msg$button", buttons);
		pd.setTransfers("$msg$function", funcs);

		redirectTo("component.Message", "setHintMessageByScript");
	}

	public void erroMessage(IRequestCycle cycle) throws Exception {
		PageData pd = getPageData();
		log.error(pd.getParameter("message"));
	}

}